package gttp.nspa.client.adm.ui;

import gttp.nspa.client.adm.activity.ICustomerList;
import gttp.nspa.client.adm.event.CustomerActionEvent;
import gttp.nspa.shared.om.Customer;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.editor.client.Editor.Path;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.client.loader.RpcProxy;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;
import com.sencha.gxt.data.shared.SortDir;
import com.sencha.gxt.data.shared.SortInfo;
import com.sencha.gxt.data.shared.loader.PagingLoadConfig;
import com.sencha.gxt.data.shared.loader.PagingLoadResult;
import com.sencha.gxt.data.shared.loader.PagingLoadResultBean;
import com.sencha.gxt.data.shared.loader.PagingLoader;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutData;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.event.CellDoubleClickEvent;
import com.sencha.gxt.widget.core.client.event.CellDoubleClickEvent.CellDoubleClickHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.GridSelectionModel;
import com.sencha.gxt.widget.core.client.grid.LiveGridView;
import com.sencha.gxt.widget.core.client.grid.LiveToolItem;
import com.sencha.gxt.widget.core.client.toolbar.SeparatorToolItem;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;

public class CustomerList implements ICustomerList {

    public static final String NAME = "Customers";

    static interface CustomerProps extends PropertyAccess {

        @Path("id")
        ModelKeyProvider<Customer> key();

        ValueProvider<Customer, Customer> self();
    }

    private VerticalLayoutContainer      con;
    private Grid<Customer>               grid;
    private PagingLoader                 loader;
    private ListStore<Customer>          store;
    private GridSelectionModel<Customer> selModel;

    private ToolBar                      tb;
    private TextButton                   btnCreate;

    private Presenter                    presenter;
    private boolean                      dirty = true;

    @Inject
    CustomerList(EventBus eventBus) {
        loader = new PagingLoader(new RpcProxy<PagingLoadConfig, PagingLoadResult>() {

            public void load(final PagingLoadConfig cfg, final AsyncCallback<PagingLoadResult> callback) {
                List<? extends SortInfo> sorts = cfg.getSortInfo();
                String[] orders = new String[sorts.size() + 1];
                int idx = 0;
                for (SortInfo sort : sorts) {
                    String field = sort.getSortField();
                    orders[idx++] = sort.getSortDir() == SortDir.DESC ? "-" + field : field;
                }
                orders[idx] = "-createdTime";
                presenter.onListCustomerRequest(cfg.getOffset(),
                                                cfg.getLimit(),
                                                orders,
                                                new AsyncCallback<List<Customer>>() {

                                                    public void onSuccess(List<Customer> list) {
                                                        PagingLoadResultBean page = new PagingLoadResultBean();
                                                        page.setData(list);
                                                        page.setOffset(cfg.getOffset());
                                                        page.setTotalLength(cfg.getOffset() + list.size());
                                                        callback.onSuccess(page);
                                                    }

                                                    public void onFailure(Throwable caught) {
                                                        callback.onFailure(caught);
                                                    }

                                                });
                dirty = false;
            }
        });

        ArrayList colList = new ArrayList();
        CustomerProps colProps = GWT.create(CustomerProps.class);
        store = new ListStore<Customer>(colProps.key());

        selModel = new GridSelectionModel();

        grid = new Grid(store, new ColumnModel(buildColumnConfigs(colProps, colList)));
        grid.setLoadMask(true);
        grid.setLoader(loader);
        grid.setSelectionModel(selModel);
        grid.setView(new LiveGridView());
        grid.getView().setForceFit(true);
        grid.addCellDoubleClickHandler(new CellDoubleClickHandler() {

            public void onCellClick(CellDoubleClickEvent event) {
                Customer sel = selModel.getSelectedItem();
                presenter.onEditCustomerRequest(sel);
            }
        });

        tb = new ToolBar();
        tb.setSpacing(4);
        buildToolbar(tb);
        BoxLayoutData bld = new BoxLayoutData();
        bld.setFlex(0.75);
        tb.add(new LiveToolItem(grid), bld);

        con = new VerticalLayoutContainer();
        con.add(tb, new VerticalLayoutData(1, -1));
        con.add(grid, new VerticalLayoutData(1, 1));

        eventBus.addHandler(CustomerActionEvent.TYPE, new CustomerActionEvent.Handler() {

            public void onAction(CustomerActionEvent event) {
                switch (event.actionType) {
                    case CREATED:
                        customerAdded(event.customer);
                        break;

                    case UPDATED:
                        customerModified(event.customer);
                        break;

                    case DELETED:
                        customerRemoved(event.customer);
                        break;
                }
            }
        });
    }

    public void setPresenter(Presenter presenter) {
        this.presenter = presenter;
        reload(false);
    }

    public void reload(boolean force) {
        if (presenter != null && (force || dirty)) {
            loader.load();
        }
    }

    public void customerAdded(Customer cust) {
        store.add(0, cust);
        dirty = true;
    }

    public void customerModified(Customer cust) {
        store.update(cust);
        dirty = true;
    }

    public void customerRemoved(Customer cust) {
        store.remove(cust);
        dirty = true;
    }

    protected void buildToolbar(ToolBar tb) {
        btnCreate = new TextButton("Create");
        btnCreate.addSelectHandler(new SelectHandler() {

            public void onSelect(SelectEvent event) {
                presenter.onCreateButtonClicked();
            }
        });
        tb.add(btnCreate);

        tb.add(new SeparatorToolItem());
        TextButton btnReload = new TextButton("Reload");
        btnReload.addSelectHandler(new SelectHandler() {

            public void onSelect(SelectEvent event) {
                reload(true);
            }
        });
        tb.add(btnReload);
    }

    protected List buildColumnConfigs(CustomerProps props, List l) {
        ColumnConfig col;

        col = new ColumnConfig(props.self(), 100, "Tên");
        col.setCell(new AbstractCell<Customer>() {

            public void render(Context context, Customer value, SafeHtmlBuilder sb) {
                String name = value.getName();
                String addr = value.getAddress() != null ? value.getAddress() : "";
                String html = name + "</br><span style='color:green'>" + addr + "</span>";
                sb.appendHtmlConstant(html);
            }
        });
        l.add(col);

        col = new ColumnConfig(props.self(), 100, "Liên lạc");
        col.setCell(new AbstractCell<Customer>() {

            public void render(Context context, Customer value, SafeHtmlBuilder sb) {
                String phone = value.getPhone() != null ? value.getPhone() : "";
                String email = value.getEmail() != null ? value.getEmail() : "";
                String html = phone + "</br><span style='color:green'>" + email + "</span>";
                sb.appendHtmlConstant(html);
            }
        });
        l.add(col);

        return l;
    }

    public Widget asWidget() {
        return con;
    }

    public String toString() {
        return NAME;
    }
}
